package com.cicc.beergamevirtualsimulationsystem.service.recordInit;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.cicc.beergamevirtualsimulationsystem.common.enums.userTypeEnum.RoleType;
import com.cicc.beergamevirtualsimulationsystem.entity.RecordDetailEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RecordEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RoleBindingEntity;
import lombok.Setter;

import java.util.*;

@Setter
public abstract class BaseRecordInit {
    // 所有玩家
    protected Map<String, RoleBindingEntity> roleBindingEntityMap;
    // 参数配置信息(期初库存)
    protected Map<Integer, Integer> paramMap;
    // 上1周所有用户记录
    protected Map<String, RecordEntity> recordEntityMapOne;
    // 上n周所有用户记录
    protected Map<String, RecordEntity> recordEntityMapN;
    // 上1周所有用户记录明细
    protected Map<String, RecordDetailEntity> recordDetailEntityMapOne;
    // 上n周所有用户记录明细
    protected Map<String, RecordDetailEntity> recordDetailEntityMapN;
    // 到货周期
    protected Integer deliveryCycle;
    // 房间id
    protected String roomId;
    // 周期
    protected Integer period;

    protected Integer orderNum;

    public RecordDTO init(RoleBindingEntity roleBindingEntity, Integer orderNum){
        this.orderNum = orderNum;

        Integer orderTotal = 0;
        // 初始化记录明细
        List<RecordDetailEntity> recordDetailEntities = new ArrayList<>();
        List<Object> downStreamIds = JSONUtil.parseArray(roleBindingEntity.getDownStreamIds()).stream().toList();
        for (Object downStreamId : downStreamIds) {
            RecordDetailEntity recordDetailEntity = period == 1 ? initRecordDetailFirstPeriod((String) downStreamId) : initRecordDetailOtherPeriod((String) downStreamId, roleBindingEntity.getUserId());
            recordDetailEntity.setPeriod(period);
            recordDetailEntity.setUserId(roleBindingEntity.getUserId());
            recordDetailEntity.setDownStreamId((String) downStreamId);
            recordDetailEntity.setReceivingCycle(period + deliveryCycle);
            recordDetailEntities.add(recordDetailEntity);

            orderTotal += recordDetailEntity.getOrderQuantity();
        }
        // 初始化记录
        RecordEntity recordEntity = period == 1 ? initRecordFirstPeriod(roleBindingEntity, orderTotal) : initRecordOtherPeriod(roleBindingEntity, orderTotal);
        recordEntity.setRoomId(roomId);
        recordEntity.setUserId(roleBindingEntity.getUserId());
        recordEntity.setUserRole(roleBindingEntity.getRoleType());
        recordEntity.setPeriod(period);
        recordEntity.setOrderTotal(orderTotal);
        recordEntity.setOweTotal(orderTotal);

        RecordDTO recordDTO = new RecordDTO();
        recordDTO.setRecordEntity(recordEntity);
        recordDTO.setRecordDetailEntityList(recordDetailEntities);
        return recordDTO;
    }

    public abstract RecordDetailEntity initRecordDetailFirstPeriod(String downStreamId);
    public abstract RecordDetailEntity initRecordDetailOtherPeriod(String downStreamId, String userId);

    protected RecordEntity initRecordFirstPeriod(RoleBindingEntity roleBindingEntity, Integer orderTotal){
        RecordEntity recordEntity = new RecordEntity();
        // 累计欠货量
        Integer accumulateOweTotal = setAccumulateOweTotal(orderTotal);

        recordEntity.setAccumulateOweTotal(accumulateOweTotal);
        recordEntity.setOpeningInventory(paramMap.get(roleBindingEntity.getRoleType()));
        recordEntity.setEndingInventory(recordEntity.getOpeningInventory());
        recordEntity.setReceiverTotal(0);
        recordEntity.setUpStreamOweTotal(0);
        recordEntity.setUpStreamAccumulateOweTotal(0);
        recordEntity.setAsset(0);
        return recordEntity;
    };

    protected RecordEntity initRecordOtherPeriod(RoleBindingEntity roleBindingEntity, Integer orderTotal){
        RecordEntity recordEntity = new RecordEntity();
        // 收货量
        Integer receiverTotal = setReceiverTotal(roleBindingEntity.getUserId());

        recordEntity.setOpeningInventory(recordEntityMapOne.get(roleBindingEntity.getUserId()).getEndingInventory());
        recordEntity.setEndingInventory(recordEntity.getOpeningInventory());
        recordEntity.setAccumulateOweTotal(recordEntityMapOne.get(roleBindingEntity.getUserId()).getAccumulateOweTotal() + orderTotal);
        recordEntity.setUpStreamOweTotal(ObjUtil.isNotNull(recordDetailEntityMapN.get(roleBindingEntity.getUserId())) ? recordDetailEntityMapN.get(roleBindingEntity.getUserId()).getOweQuantity() : 0);
        recordEntity.setUpStreamAccumulateOweTotal(recordEntityMapOne.get(roleBindingEntity.getUserId()).getUpStreamAccumulateOweTotal() - receiverTotal);
        recordEntity.setAsset(recordEntityMapOne.get(roleBindingEntity.getUserId()).getAsset());
        recordEntity.setReceiverTotal(receiverTotal);
        return recordEntity;
    };

    public abstract Integer getType();

    public abstract Integer setReceiverTotal(String userId);
    public abstract Integer setAccumulateOweTotal(Integer orderTotal);

    private Map<String, String> initUserName(List<RoleBindingEntity> roleBindingEntities) {
        // 根据角色类型分组
        HashMap<Integer, List<RoleBindingEntity>> roleGroup = new HashMap<>();
        for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
            roleGroup.computeIfAbsent(roleBindingEntity.getRoleType(), key -> new ArrayList<>()).add(roleBindingEntity);
        }

        Map<String, String> userNames = new HashMap<>();
        // 初始化名称
        roleGroup.forEach((key, value) -> {
            Map<String, String> map = setName(key, value);
            userNames.putAll(map);
        });
        return userNames;
    }

    private Map<String, String> setName(Integer key, List<RoleBindingEntity> value) {
        Map<String, String> userName = new HashMap<>();

        String name = null;
        if(Objects.equals(key, RoleType.FACTORY.getCode())){
            name = RoleType.FACTORY.getDesc();
        } else if(Objects.equals(key, RoleType.SUPPLIER.getCode())){
            name = RoleType.SUPPLIER.getDesc();
        } else if(Objects.equals(key, RoleType.RETAILER.getCode())){
            name = RoleType.SUPPLIER.getDesc();
        }
        char a = 97;
        for (int i = 0; i < value.size(); i++) {
            userName.put(value.get(i).getUserId(), name + (a + i));
        }
        return userName;
    }
}
